home *** CD-ROM | disk | FTP | other *** search
- ; CD Ver. 1.0
- ;
- ; This program replaces COMMAND.COM's CD. Basically, it works
- ; the same way. The current directory is changed to the pathname
- ; given as the only parameter. But, in case of an error, this new
- ; CD-command behaves differently: If the given parameter starts
- ; with '\' or '/', the current directory isn't changed and the
- ; program aborts with an error message.
- ; If the parameter only specifies part of a pathname and such a
- ; subdirectory doesn't exist in the current directory, the
- ; environement variable CDPATH is evaluated. This variable
- ; specifies a list of subdirectories, separated by ';', in which
- ; we have to look for the directory to change to.
- ; If we still aren't successfull in changing to that directory,
- ; it's time for an error message.
- ; The program, once loaded, stays in RAM and works as an
- ; extension of the command interpreter.
- ; The user may specify if the command CD without a parameter
- ; changes to the root directory or prints the pathname of the
- ; current directory.
- ;
- ; Copyright (C) 1987 by Urs Zurbuchen, Switzerland
- ;
- ; You may freely distribute this program unless you
- ; include the sources and don't touch this header.
- ; Commercial usage is prohibited.
- ;
- ; Requirements:
- ; This program requires that the command editor CED
- ; (by C.J. Dunford) is installed.
- ;
- ; Restrictions:
- ; The environement variable is evaluated when the program
- ; is loaded. Changes to the environement after the
- ; program is loaded into memory are NOT recognized.
- ; CDPATH may not be longer than CDLENGTH characters. You
- ; can change this value in the sources below.
- ;
- ; Usage: CD
- ; CD pathname
- ;
- ; Installation: NEWCD {r | p}
- ; r: change to root
- ; p: print current directory
- ; Default is r
- ;
- ; Assembly: MASM newcd;
- ; LINK newcd;
- ; EXE2BIN newcd newcd.com
- ;
- ; Author: Urs Zurbuchen
- ;
- ; Date: February 15, 1987
- ;
- ; Revisions:
- ; Date Who What
- ;
- ;----------------------------------------------------------------------
-
- ; adjust the following global according to the processor used
- is_8088 equ 0 ; you won't have those fancy '286
- ; instructions if true
- if is_8088
- .8086
- else
- .286c ; this requires MASM 4.0
- endif
-
-
- ; some global constants
- cr equ 13 ; CarriageReturn
- lf equ 10 ; LineFeed
- space equ 32 ; (what do you guess :-)
- tab equ 9 ; Tabulator
-
- ; definitions for the CED interface
- ced equ 0ffh ; special DOS function for CED services
- enqueue equ 0 ; Subfunction to CED: enqueue command
- dequeue equ 1 ; Subfunction to CED: dequeue command
- ced_dos equ 1 ; CED parameter: command at DOS prompt
- ced_usr equ 2 ; CED parameter: command in user prg
-
- ; configurable constant
- cdlength equ 255 ; max. string length of CDPATH
-
- ; here follows the program section
- cseg segment para public 'code'
- assume cs:cseg, ds:cseg, es:cseg
-
- ; initialization
- org 100h
-
- ;-----------------------
- ; Installation procedure
- ;-----------------------
- main proc far
- jmp install ; go to installation
-
- ; datastructures
- pwd: db 0 ; 0: change to root
- ; 1: print current dir
- flag: db 0 ; 0: partial pathname
- ; 1: pathname starts with '\' or '/'
- root: db '\',0 ; pathname for the root
- path: db 67 dup (?) ; working-storage for pathnames
- work: db 100 dup (?) ; working-storage (give it some reserves)
- cdpath: db cdlength + 1 dup (?) ; CDPATH environement
-
- ; error messages
- msg1$ db 'cd: directory not found', cr, lf, '$'
- msg2$ db 'cd: HELP! HELP! Cannot change to root directory', cr, lf, '$'
- msg3$ db 'cd: Cannot get current directory', cr, lf, '$'
- msg4$ db 'cd: Too many parameters', cr, lf, '$'
-
- ;-----------------
- ; the CD procedure
- ;-----------------
- newcd proc far
- mov byte ptr [si],cr ; null out the users input
- mov bp,dx
- push ds ; save data segment
- pop es
- push cs ; set data segment context
- pop ds
-
- cd_1: mov al,byte ptr es:[bp] ; test for parameters
- inc bp
- cmp al,cr ; end of input reached ?
- jz cd_noparam
- cmp al,space ; leading spaces and tabs are ok
- jz cd_1
- cmp al,tab
- jz cd_1
- jmp cd_normal ; any other char inidicates pathname
-
- cd_noparam:
- cmp byte ptr [pwd],1 ; true, if we have to print current dir
- jz cd_prcur
-
- ; change current dir to root
- mov dx,offset root ; ds:dx points to pathname for root
- mov ah,3bh ; change current directory
- int 21h
- jnc cd_nopara_1 ; avoid 'out of range'
- jmp err_trouble ; you're in real trouble if this
- ; doesn't work
- cd_nopara_1:
- jmp cd_end
-
- cd_prcur: ; print current directory
- mov si,offset path ; ds:si points to storage for pathname
- mov ah,19h ; get current drive
- int 21h
- add al,'A' ; change to human readable characters
- mov ah,':'
- mov word ptr [si],ax ; save drive name for print
- inc si
- inc si
- mov byte ptr [si],'\' ; we don't get the first \ from DOS
- inc si ; so we have to insert it
- mov dl,0 ; we'd like the current drive
- mov ah,47h ; get current directory
- int 21h
- jnc cd_prcur_1 ; avoid 'out of range'
- jmp err_getcurrent ; can't imagine an error, but nobody's
- ; perfect
- cd_prcur_1:
- mov bx,1 ; file handle is standard output
- mov dx,offset path ; start of text to print
- xor cx,cx ; get length of string to print
- mov bp,dx
- cd_pr1: inc cx ; one char is always there ('\')
- inc bp ; test next (!) character
- cmp byte ptr ds:[bp],0 ; end of string is indicated by zero
- jnz cd_pr1
- mov ah,40h ; write to a file or device
- int 21h ; print the string
- jmp cd_end ; no test for error
-
- cd_normal: ; test for additional parameters
- mov di,offset path ; init pointers
- mov cx,0
- cmp al,'\' ; we have to know if the parameter
- jz cd_mark ; starts with '\' or '/', or if it's
- cmp al,'/' ; only a partial pathname
- jnz cd_2
- cd_mark: mov byte ptr [flag],1
-
- cd_2: mov byte ptr [di],al ; save parameter
- inc di
- inc cx ; compute length of parameter in CX
- mov al,byte ptr es:[bp] ; get next character
- inc bp
- cmp al,cr ; end of input reached ?
- jz cd_cd
- cmp al,space ; space and tab are delimiters
- jz cd_3
- cmp al,tab
- jz cd_3
- jmp cd_2 ; any other char belongs to pathname
-
- cd_3: mov al,byte ptr es:[bp] ; test for additional parameters
- inc bp
- cmp al,cr ; end of input reached ?
- jz cd_cd
- cmp al,space ; space and tab are ok at the tail
- jz cd_3
- cmp al,tab
- jz cd_3
- jmp err_toomany ; any other char is bad
-
- cd_cd: mov byte ptr [di], 0 ; change pathname to ASCIIZ
- mov dx,offset path ; ds:dx points to pathname
- mov ah,3bh ; change current directory
- int 21h
- jnc cd_end ; exit, if no error occurs
- cmp byte ptr [flag],0 ; true if partial pathname
- jnz err_invalidir ; full pathname leads to error
-
- push ds ; update es. now, we can use the
- pop es ; string commands
- mov bp,offset cdpath ; ds:bp points to next path in CDPATH
- mov si,offset path ; ds:si points to parameter
-
- cd_path: ; try each entry in CDPATH as first part of the pathname
- ; we copy the next entry in CDPATH to the working-storage
- ; and append the actual parameter (the partial pathname)
-
- cmp byte ptr ds:[bp],0 ; end of CDPATH is indicated by zero
- jz err_invalidir ; I'm sorry, but I can't find that dir
- mov di,offset work ; es:si points to working-storage
- cd_copy:
- mov al,byte ptr es:[bp] ; copy entry in CDPATH
- cmp al,0 ; end reached?
- jz cd_p1
- cmp al,';' ; end is indicated by zero or ';'
- jz cd_p1
- stosb
- inc bp
- jmp cd_copy
-
- cd_p1: inc bp ; adjust pointer
- mov byte ptr [di],'\' ; insert delimiter
- inc di
- push cx
- push si
- repnz movsb ; append parameter
- pop si
- pop cx
- mov byte ptr [di],0 ; mark end
- mov dx,offset work ; ds:dx points to the pathname
- mov ah,3bh
- int 21h
- jc cd_path ; repeat if still no valid directory
-
- cd_end: mov byte ptr [flag],0 ; reset flag
- ret ; exit to CED
-
- newcd endp
-
-
- ;--------------
- ; error handler
- ;--------------
- error proc near
- err_trouble: ; you're in real trouble if we can't change to the root
- ; I hope you have a real good 'disk doctor'
- mov dx,offset msg2$
- jmp err_common
-
- err_getcurrent: ; can't get the current directory's pathname
- ; This isn't much better as the above
- mov dx,offset msg3$
- jmp err_common
-
- err_toomany: ; you specified too many parameters (only one allowed)
- mov dx,offset msg4$
- jmp err_common
-
- err_invalidir: ; you specified an invalid pathname
- mov dx,offset msg1$
-
- err_common: ; common point for error output
- mov ah,9 ; print string
- int 21h
- jmp cd_end
-
- error endp
-
-
- ;-------------------------------------------------------------------
- ; This is the installation routine. It queues the two commands above
- ; into the CED command editor. It terminates but leaves the command
- ; routines resident.
- ;-------------------------------------------------------------------
- install:
- push cs
- pop ds
- push ds
- pop es
-
- mov ah,ced ; request CED service from DOS
- mov al,enqueue ; enqueue a new command
- mov bl,ced_dos ; CD is only active at DOS prompt
- mov si,offset cd$ ; pointer to command name
- mov di,offset newcd ; pointer to service routine
- int 21h
- jnc inst_ok ; no error: exit
-
- mov dx, offset msg_inst1$ ; only error 8 is possible here
- inst_err:
- mov ah, 9 ; print string
- int 21h
- int 20h ; exit without staying resident
-
- inst_ok:
- push ds
- mov si,2ch ; ds:si points to environement
- mov ds,word ptr [si]
- mov si,0
- mov di,offset cdpath ; es:di points to space for CDPATH string
- mov cx,0
-
- inst_search: ; search for environement variable CDPATH
- cmp byte ptr [si],0 ; test for end of environement string
- jz inst_end
- mov bp,offset cdpath$ ; name of environement variable
-
- inst_loop: ; compare an environement entry with
- lodsb ; the variable name
- inc bp
- cmp al,byte ptr es:[bp-1]
- jnz inst_skip
- cmp al,'='
- jnz inst_loop
- jmp inst_copy
-
- inst_skip: ; skip to next entry
- inc si
- cmp byte ptr [si-1],0
- jnz inst_skip
- jmp inst_search
-
- inst_copy: ; copy definition
- lodsb ; get a char
- stosb
- inc cx ; max. string length is cdlength
- cmp cx,cdlength
- jnc inst_end
- or al,al ; end reached? (marked by zero)
- jnz inst_copy ; no: copy more
-
- inst_end:
- mov byte ptr [di],0 ; mark end of CDPATH
- pop ds
-
- mov cx,0
- mov bp,[80h]
- mov cl,byte ptr es:[bp] ; any parameter given?
- jcxz inst_tsr ; no: exit without changing the flag
-
- inst_para:
- mov al,es:[bp+1] ; leading spaces and tabs are ok
- inc bp
- cmp al,space
- jz inst_para
- cmp al,tab
- jz inst_para
- or al,20h ; change into lower case
- cmp al,'p' ; p means 'print current dir'
- jz inst_print
- loopnz inst_para
- jmp inst_tsr ; don't change flag: 'go to root'
-
- inst_print:
- mov byte ptr [pwd],1 ; set flag to 'print current dir'
-
- inst_tsr:
- mov dx,offset install ; ok: terminate/resident
- int 27h
- main endp
-
- ; messages for installation procedure
- msg_inst1$ db 'install cd: CED command list full', cr, lf, '$'
-
- ; command name
- cd$ db 'cd', cr
-
- ; environement variable name
- cdpath$ db 'CDPATH='
-
- cseg ends
- end main